package wsi.function.oauth;

import java.awt.Desktop;
import java.net.URI;
import java.util.logging.Logger;

import javax.swing.JOptionPane;

import org.rygh.gui.swing.USwing;
import org.scribe.builder.ServiceBuilder;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.model.Verifier;
import org.scribe.oauth.OAuthService;

import wsi.db.WebCache;
import wsi.detect.Caller.CallResult;
import wsi.function.Function;
import wsi.script.AppConfig;

public class OAuthController {
	private final Logger log = Logger.getLogger(getClass().getName());

	private Class<? extends OAuthApi> klass;
	private OAuthService service;
	private Token accessToken;

	@SuppressWarnings("unchecked")
	public OAuthController(String klassName) {
		USwing.initLookAndFeel();

		try {
			klass = (Class<? extends OAuthApi>) Class.forName(klassName);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public boolean connect(Function function) {
		OAuthApi api = null;

		try {
			api = klass.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

		service = new ServiceBuilder().provider(klass)
				.apiKey(api.getConsumerKey())
				.apiSecret(api.getConsumerSecret()).build();

		Token requestToken = service.getRequestToken();

		if (function != null && function.getToken() != null)
			accessToken = function.getToken();
		else {
			String authUrl = service.getAuthorizationUrl(requestToken);

			log.info(authUrl);

			try {
				Desktop.getDesktop().browse(new URI(authUrl));
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}

			String str = JOptionPane
					.showInputDialog("Please input the authentication code.");

			Verifier v = new Verifier(str);

			accessToken = service.getAccessToken(requestToken, v);

			if (function != null) {
				function.setToken(accessToken);
				function.save();
			}
		}

		return true;
	}

	public CallResult get(String url) {
		String content = null;

		// log.info("GET " + url);

		boolean cache = AppConfig.shared().isWebCacheOn();

		if (cache) {
			content = WebCache.fetch(url);

			if (content != null) {
				// log.info("cache hit: " + WebCache.getHashCode(url));
				return new CallResult(content, true);
			}
		}

		OAuthRequest request = new OAuthRequest(Verb.GET, url);
		service.signRequest(accessToken, request);

		Response response = request.send();

		content = response.getBody();

		return new CallResult(content, false);
	}

	public CallResult post(String url, String... params) {
		String content = null;

		StringBuilder key = new StringBuilder();
		key.append(url + "?");

		for (int i = 0; i < params.length; i += 2)
			key.append(String.format("%s=%s&", params[i], params[i + 1]));

		String nurl = key.toString();

		boolean cache = AppConfig.shared().isWebCacheOn();

		if (cache) {
			content = WebCache.fetch(nurl);

			if (content != null) {
				// log.info("cache hit: " + WebCache.getHashCode(nurl));
				return new CallResult(content, true);
			}
		}

		System.out.println("post " + nurl);

		OAuthRequest request = new OAuthRequest(Verb.POST, url);

		for (int i = 0; i < params.length; i += 2)
			request.addBodyParameter(params[i], params[i + 1]);

		service.signRequest(accessToken, request);

		Response response = request.send();

		content = response.getBody();

		return new CallResult(content, false);
	}

}
